package com.lemon.cloud.interceptor.annotation;

import com.lemon.cloud.command.Command;
import com.lemon.cloud.command.CommandRepository;
import com.lemon.cloud.interceptor.CommandInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * @author lemon
 * @version 1.0
 * @description: TODO
 * @e Create by lemon on 2019-09-15 09:30
 */
@Slf4j
@Component
public class CommandInterceptorAnnotationBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware {
    private ApplicationContext applicationContext;

    @Autowired
    private CommandRepository commandRepository;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        Class pcommandInterceptorClass = bean.getClass();

        if (bean.getClass().isAnnotationPresent(PreCommandInterceptor.class)) {
            CommandInterceptor commandInterceptor = (CommandInterceptor) this.applicationContext.getBean(pcommandInterceptorClass);
            this.registedPreCommandInterceptor(commandInterceptor);
        }

        if (bean.getClass().isAnnotationPresent(PostCommandInterceptor.class)) {
            CommandInterceptor commandInterceptor = (CommandInterceptor) this.applicationContext.getBean(pcommandInterceptorClass);
            this.registedPostCommandInterceptor(commandInterceptor);
        }

        return bean;
    }

    /**
     * @param commandInterceptor
     * @return void
     * @description
     * @author lemon
     * @date 2019-09-15 09:36
     */
    private void registedPreCommandInterceptor(CommandInterceptor commandInterceptor) {
        PreCommandInterceptor preInterceptorAnnotation = commandInterceptor.getClass().getDeclaredAnnotation(PreCommandInterceptor.class);
        Class<? extends Command>[] commandArray = preInterceptorAnnotation.commands();
        log.info("PreCommandInterceptor[{}] interceptor commands: {}", commandInterceptor.getClass(), StringUtils.join(commandArray, ","));

        if (ArrayUtils.isNotEmpty(commandArray)) {
            this.commandRepository.registedPreCommandInterceptor(commandInterceptor);
        }
    }

    /**
     * @param commandInterceptor
     * @return void
     * @description
     * @author lemon
     * @date 2019-09-15 09:39
     */
    private void registedPostCommandInterceptor(CommandInterceptor commandInterceptor) {
        PostCommandInterceptor preInterceptorAnnotation = commandInterceptor.getClass().getDeclaredAnnotation(PostCommandInterceptor.class);
        Class<? extends Command>[] commandArray = preInterceptorAnnotation.commands();
        log.info("PostCommandInterceptor[{}] interceptor commands: {}", commandInterceptor.getClass(), StringUtils.join(commandArray, ","));

        if (ArrayUtils.isNotEmpty(commandArray)) {
            this.commandRepository.registedPostCommandInterceptor(commandInterceptor);
        }
    }
}
